package io.gitee.shengzheng1999.esbcommon.common.utils;

import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Map;

import org.springframework.util.StreamUtils;

import com.alibaba.fastjson.JSONObject;


/**
 * @className		: HttpUtil
 * @description	: HTTP访问工具类
 * @summary		:
 * @history		:
 * ------------------------------------------------------------------------------
 * date			version		modifier		remarks                   
 * ------------------------------------------------------------------------------
 * 2021/01/01	1.0.0		sheng.zheng		初版
 *
 */
public class HttpUtil {

	/**
	 * 
	 * @methodName		: sendHttpRequest
	 * @description	: 发送HTTP请求
	 * @param httpURL	: 请求url
	 * @param httpMethod: 请求方式，为POST或GET
	 * @param headers	: 请求头，Map类型
	 * @param body		: 请求体，请求方式为POST时需要
	 * @return			: 响应结果
	 * @throws Exception
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2021/01/01	1.0.0		sheng.zheng		初版
	 *
	 */
    public static String sendHttpRequest(String httpURL, String httpMethod,
    		Map<String,String> headers, JSONObject body) throws Exception {
    	
        // 建立URL连接对象
        URL url = new URL(httpURL);
        // 创建连接
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        
        // 设置headers
        for (Map.Entry<String,String> entry : headers.entrySet()) {
        	String key = entry.getKey();
        	String value = entry.getValue();
        	conn.setRequestProperty(key, value); 
        }
        
        // 设置请求的方式
        if(httpMethod.equalsIgnoreCase("POST")) {
        	conn.setRequestMethod("POST");
        }else if(httpMethod.equalsIgnoreCase("GET")) {
        	conn.setRequestMethod("GET");
        }else {
        	throw new Exception("unsupported request method");
        }
        
        // 设置需要输出
        conn.setDoOutput(true);
        // 设置是否从httpUrlConnection读入
        conn.setDoInput(true);
        
        // 发送请求到服务器
        conn.connect();
        
        BufferedWriter writer = null;
        if(body != null) {
        	writer = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream(), "UTF-8"));
            writer.write(body.toJSONString());
            writer.close();       
        } 
                
        // 获取远程响应的内容.
        String responseContent = StreamUtils.copyToString(conn.getInputStream(), Charset.forName("utf-8"));
        conn.disconnect();
        return responseContent;
    }       
    
    /**
     * 
     * @methodName		: downloadFile
     * @description	: 下载文件
	 * @param httpURL	: 请求url
	 * @param httpMethod: 请求方式，为POST或GET
	 * @param headers	: 请求头，Map类型
	 * @param body		: 请求体，请求方式为POST时需要
     * @param filePath	: 保存的文件路径
	 * @return			: 如果有异常信息，则返回JSON字符串，否则返回空串
     * @throws Exception
     * @history		:
     * ------------------------------------------------------------------------------
     * date			version		modifier		remarks                   
     * ------------------------------------------------------------------------------
     * 2023/01/31	1.0.0		sheng.zheng		初版
     *
     */
    public static String downloadFile(String httpURL, String httpMethod,
    		Map<String,String> headers, JSONObject body,String filePath) throws Exception {
        // 建立URL连接对象
        URL url = new URL(httpURL);
        // 创建连接
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        
        String retStr = "";
        // 设置headers
        for (Map.Entry<String,String> entry : headers.entrySet()) {
        	String key = entry.getKey();
        	String value = entry.getValue();
        	conn.setRequestProperty(key, value); 
        }
        
        // 设置请求的方式
        if(httpMethod.equalsIgnoreCase("POST")) {
        	conn.setRequestMethod("POST");
        }else if(httpMethod.equalsIgnoreCase("GET")) {
        	conn.setRequestMethod("GET");
        }else {
        	throw new Exception("unsupported request method");
        }
        
        // 设置需要输出
        conn.setDoOutput(true);
        // 设置是否从httpUrlConnection读入
        conn.setDoInput(true);
        
        // 发送请求到服务器
        conn.connect();
        
        BufferedWriter writer = null;
        if(body != null) {
        	writer = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream(), "UTF-8"));
            writer.write(body.toJSONString());
            writer.close();       
        }                 
        
        int responseCode = conn.getResponseCode();
        if (responseCode == HttpURLConnection.HTTP_OK 
        	|| responseCode == HttpURLConnection.HTTP_PARTIAL) {
            String contentType = conn.getContentType();        
            //LogUtil.info("contentType = " + contentType);
            if (contentType.equalsIgnoreCase("application/json")) {
            	retStr = StreamUtils.copyToString(conn.getInputStream(), Charset.forName("utf-8"));
                conn.disconnect();
            	return retStr;
            } 
            
            // 获取远程响应的内容.
            BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
            File file = new File(filePath);
            if (file.exists()) {
            	// 如果文件已存在，则删除
            	file.delete();
            }
            OutputStream os = new FileOutputStream(file);
            int size = 0;
            byte[] buffer = new byte[1024];
            while((size = bis.read(buffer)) != -1) {
            	os.write(buffer,0,size);
            }
            os.flush();
            os.close();
            bis.close();
            conn.disconnect();            
        }else {
        	// 失败
        	throw new Exception("HTTP error code: " + responseCode);
        }
                

    	return retStr;
    }
    
    /**
     * 
     * @methodName		: uploadFile
     * @description	: 上传文件到远端服务器
     * @param httpURL	: url
     * @param params	: 附加参数
     * @param files		: 文件
     * @return
     * @throws Exception
     * @history		:
     * ------------------------------------------------------------------------------
     * date			version		modifier		remarks                   
     * ------------------------------------------------------------------------------
     * 2023/05/09	1.0.0		sheng.zheng		初版
     *
     */
    public static String uploadFile(String httpURL, Map<String,String> headers, 
    		Map<String,Object> params,String filePath)throws Exception{
    	String BOUNDARY = java.util.UUID.randomUUID().toString();
    	String PREFIX = "--"; 
    	String LINEND = "\r\n";
    	String MULTIPART_FROM_DATA = "multipart/form-data";
    	String CHARSET = "UTF-8";

    	URL uri = new URL(httpURL);

    	HttpURLConnection conn = (HttpURLConnection) uri.openConnection();
    	
        // 设置headers
        for (Map.Entry<String,String> entry : headers.entrySet()) {
        	String key = entry.getKey();
        	String value = entry.getValue();
        	conn.setRequestProperty(key, value); 
        }
        
    	conn.setReadTimeout(6 * 1000); // 缓存的最长时间
    	conn.setDoInput(true);// 允许输入
    	conn.setDoOutput(true);// 允许输出
    	conn.setUseCaches(false); // 不允许使用缓存
    	conn.setRequestMethod("POST");
    	conn.setRequestProperty("connection", "keep-alive");
    	conn.setRequestProperty("Charsert", "UTF-8");
    	conn.setRequestProperty("Content-Type", MULTIPART_FROM_DATA + ";boundary=" + BOUNDARY);

    	// 首先组拼文本类型的参数
    	StringBuilder sb = new StringBuilder();
    	for (Map.Entry<String,Object> entry : params.entrySet()){
    		sb.append(PREFIX);
    		sb.append(BOUNDARY);
    		sb.append(LINEND);
    		sb.append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + LINEND);
    		sb.append("Content-Type: text/plain; charset=" + CHARSET + LINEND);
    		sb.append("Content-Transfer-Encoding: 8bit" + LINEND);
    		sb.append(LINEND);
    		sb.append(entry.getValue());
    		sb.append(LINEND);
    	}

    	DataOutputStream outStream = new DataOutputStream(conn.getOutputStream());
    	outStream.write(sb.toString().getBytes());
    	
    	// 获取文件名
    	String fileName = filePath.substring(filePath.lastIndexOf(File.separator)+1);
    	
   		// 发送文件数据    	
		StringBuilder sb1 = new StringBuilder();
		sb1.append(PREFIX);
		sb1.append(BOUNDARY);
		sb1.append(LINEND);
		sb1.append("Content-Disposition: form-data; name=\"file\"; filename=\"" 
				+ fileName + "\"" + LINEND);
		sb1.append("Content-Type: application/octet-stream; charset=" + CHARSET + LINEND);
		sb1.append(LINEND);
		outStream.write(sb1.toString().getBytes());

		InputStream is = new FileInputStream(filePath);
		byte[] buffer = new byte[1024];
		int len = 0;
		while ((len = is.read(buffer)) != -1)
		{
			outStream.write(buffer, 0, len);
		}
		is.close();
		outStream.write(LINEND.getBytes());
    	// 请求结束标志
		byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINEND).getBytes();
		outStream.write(end_data);
		outStream.flush();

		// 得到响应码
		 String retStr = "";
		int responseCode = conn.getResponseCode();
		if (responseCode == HttpURLConnection.HTTP_OK) {
			retStr = StreamUtils.copyToString(conn.getInputStream(), Charset.forName("utf-8"));
			outStream.close();
			conn.disconnect();			
		}else {
			// 失败
			outStream.close();
			conn.disconnect();			
			throw new IOException("HTTP error code: " + responseCode);
		}
		return retStr;
    }
    
}
